#include <Windows.h>
#include <tchar.h>
#include <assert.h>

const UINT  WM_UMSG_DATA			= (WM_APP + 1001);
const UINT	WM_UMSG_REGISTER		= RegisterWindowMessage(_T("Register_MSG"));
const UINT	WM_UMSG_BROADCAST		= RegisterWindowMessage(_T("BroadCast_MSG"));
const UINT	WM_UMSG_MSGWNDCREATED	= RegisterWindowMessage(_T("MSGWndCreated_MSG"));

struct TPerson {
	UINT	m_nAge;
	TCHAR	m_szName[64];
};

LRESULT CALLBACK WndProc(HWND hWnd, UINT nMsg, WPARAM wParam, LPARAM lParam)
{	
	switch (nMsg)
	{
		case WM_CREATE:
		{
			MessageBox(hWnd, _T("Message Reciver(Demo0050) Launched!"), _T("Demo0050"), MB_OK);
			PostMessage(HWND_BROADCAST, WM_UMSG_MSGWNDCREATED, 0, 0);
			break;
		}
		case WM_COPYDATA:		
		{
			COPYDATASTRUCT* cds = (COPYDATASTRUCT*)lParam;
			TPerson* pPerson = (TPerson*)cds->lpData;

			TCHAR szTmp[129];
			_stprintf(szTmp, _T("Demo0050 Received a CopyData Messaged -- age: %d name: %s"), pPerson->m_nAge, (LPTSTR)pPerson->m_szName);
			MessageBox(NULL, szTmp, _T("Demo0050"), MB_OK);

			break;
		}
		case WM_UMSG_DATA:		
		{
			TCHAR szTmp[129];
			_stprintf(szTmp, _T("Demo0050 Received a User Messaged -- wParam: %d lParam: %d"), wParam, (LPTSTR)lParam);
			MessageBox(NULL, szTmp, _T("Demo0050"), MB_OK);
			break;
		}
		case WM_CLOSE:
		{
			SendMessage(HWND_BROADCAST, WM_UMSG_MSGWNDCREATED, 0, 1);
			PostQuitMessage(0);
			break;
		}
	}

	if (WM_UMSG_REGISTER == nMsg)
	{
		TCHAR szTmp[129];
		_stprintf(szTmp, _T("Demo0050 Received a Register Message -- wParam: %d lParam: %d"), wParam, (LPTSTR)lParam);
		MessageBox(NULL, szTmp, _T("Demo0050"), MB_OK);
	} else if (WM_UMSG_BROADCAST == nMsg) {
		TCHAR szTmp[129];
		_stprintf(szTmp, _T("Demo0050 Received a Broadcast Message -- wParam: %d lParam: %d"), wParam, (LPTSTR)lParam);
		MessageBox(NULL, szTmp, _T("Demo0050"), MB_OK);
	}
	
	return ::DefWindowProc(hWnd, nMsg, wParam, lParam);
}

//////////////////////////////////////////////////////////////////////////
bool RegisterWndClass(const TCHAR* szClsName, WNDPROC fnWndProc)
{
	WNDCLASSEX wcs		= {0};
	wcs.cbSize			= sizeof(WNDCLASSEX);
	wcs.hbrBackground	= (HBRUSH)GetStockObject(COLOR_APPWORKSPACE);
	wcs.lpszClassName	= szClsName;
	wcs.lpfnWndProc		= fnWndProc;
	wcs.hCursor			= LoadCursor(NULL, MAKEINTRESOURCE(IDC_ARROW));
	wcs.hIcon			= LoadIcon(GetModuleHandle(NULL), MAKEINTRESOURCE(IDI_APPLICATION));
	wcs.style			= CS_VREDRAW|CS_HREDRAW;
	
	return (0 != RegisterClassEx(&wcs));
}

//////////////////////////////////////////////////////////////////////////
HWND CreateWnd(const TCHAR* szClsName, const TCHAR* szWndCaption, HWND hParent = NULL, 
			   DWORD dwStyle = WS_POPUP|WS_VISIBLE|WS_SYSMENU|WS_CAPTION, 
			   DWORD dwStyleEx = 0)
{
	if (NULL != szClsName)
	{
		HWND hWnd = CreateWindowEx(dwStyleEx, szClsName, szWndCaption, dwStyle, 
			                       0, 0, 800, 480, HWND_MESSAGE, NULL, GetModuleHandle(NULL), NULL);
	
		if (NULL != hWnd && IsWindow(hWnd))
		{
			return hWnd;
		}
	}
	return NULL;
}

//////////////////////////////////////////////////////////////////////////
void RunMessageLoop()
{
	MSG Msg;
	while (true)
	{
		while (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE))
		{
			if (WM_QUIT == Msg.message)
			{
				return;
			}

			TranslateMessage(&Msg);
			DispatchMessage(&Msg);
		}
	}
}

//////////////////////////////////////////////////////////////////////////
BOOL WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPreInstance, LPTSTR szCmdLine, int nShowCmd)
{
	const TCHAR* szClsName		= _T("Win32App");
	const TCHAR* szWndCaption	= _T("Demo0050");

	if (RegisterWndClass(szClsName, WndProc))
	{
		if (NULL != CreateWnd(szClsName, szWndCaption))
		{
			RunMessageLoop();
		}
	}

	return TRUE;
}
